package com.weixin.project.Service;

import com.weixin.project.Config.Config;
import com.weixin.project.Dao.PracticeHistoryDao;
import com.weixin.project.Dao.UserDao;
import com.weixin.project.Entity.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import java.util.*;

@Service
public class TestService {
    @Value("${spring.profiles.active}")
    private String env;
    @Autowired
    UserDao userDao;
    @Autowired
    UserService userService;
    @Autowired
    PracticeHistoryDao practiceHistoryDao;
    @Autowired
    QuestionService questionService;
    private Map<String, Double> percentMap = new HashMap<>();
    private Map<String, Integer> lowPracticeNumMap = new HashMap<>();
    private Map<String, Integer> highPracticeNumMap = new HashMap<>();
    private Map<String, Map<Integer, Double>> correctMap = new HashMap<>();
    private Integer userNum = 1000;
    //普通用户，占比95%，正确率依据题目difficulty，刷题数量为20-40
    private final String NORMAL = "normal";
    //顶级考生，占比4%，正确率依据题目difficulty，刷题数量为40-60
    private final String TOP = "top";
    //恶意用户，占比1%，正确率始终为25%，刷题数量为1-100
    private final String EVIL = "evil";
    private Integer cur_bank;
    private Integer cur_chapter;
    //一页 == 一题
    private Integer page;
    //用户选取章节第一题做题的概率
    private final Double FIRST_PROBLEM = 0.6;
    private final Double NEXT_PROBLEM = 0.8;
    private final Double STOP_CUR_BANK = 0.95;
    private final Double STOP_CUR_CHAPTER = 0.65;

    private void initMap(){
        System.out.println("初始化......");
        percentMap.put(NORMAL, 0.95);
        percentMap.put(TOP, 0.04);
        percentMap.put(EVIL, 0.01);

        lowPracticeNumMap.put(NORMAL, 20);
        highPracticeNumMap.put(NORMAL, 40);
        lowPracticeNumMap.put(TOP, 40);
        highPracticeNumMap.put(TOP, 60);
        lowPracticeNumMap.put(EVIL, 1);
        highPracticeNumMap.put(EVIL, 100);

        Map<Integer, Double> normalCorrect = new HashMap<>();
        normalCorrect.put(1, 0.7);
        normalCorrect.put(2, 0.5);
        normalCorrect.put(3, 0.3);
        correctMap.put(NORMAL, normalCorrect);
        Map<Integer, Double> topCorrect = new HashMap<>();
        topCorrect.put(1, 0.9);
        topCorrect.put(2, 0.8);
        topCorrect.put(3, 0.6);
        correctMap.put(TOP,topCorrect);
        Map<Integer, Double> evilCorrect = new HashMap<>();
        evilCorrect.put(1, 0.25);
        evilCorrect.put(2, 0.25);
        evilCorrect.put(3, 0.25);
        correctMap.put(EVIL, evilCorrect);
    }

    private void questionLoc(Integer bankId){
        cur_bank = bankId;
        List<Chapter> chapters = questionService.findChapters(cur_bank);
        cur_chapter = chapters.get(new Random().nextInt(chapters.size())).getId();
        //一页 == 一题
        if (new Random().nextDouble() < FIRST_PROBLEM) page = 0;
        else page = new Random().nextInt(questionService.countQuestionsOfChapter(cur_chapter));
    }

    private void questionLoc(){
        List<QuestionBank> allQuestionBanks = questionService.findAllQuestionBanks();
        Integer bankId = allQuestionBanks.get(new Random().nextInt(allQuestionBanks.size())).getId();
        questionLoc(bankId);
    }

    private void transformQuestion(){
        Question question;
        Double c = new Random().nextDouble();
        //在当前库中继续做题
        if (c < STOP_CUR_BANK) {
            Double q = new Random().nextDouble();
            //在当前章节继续做题
            if (q < STOP_CUR_CHAPTER) {
                Double n = new Random().nextDouble();
                //做下一道题目
                if (n < NEXT_PROBLEM) {
                    page++;
                    question = questionService.findQuestionByChapterId(cur_chapter, page);
                    // 题目存在，直接返回
                    if (question != null) return;
                    // 题目不存在，随机选页
                    else {
                        page = new Random().nextInt(questionService.countQuestionsOfChapter(cur_chapter));
                    }
                }
                //在当前章节随机选页
                else {
                    page = new Random().nextInt(questionService.countQuestionsOfChapter(cur_chapter));
                }
            }
            //在其它章节做题
            else {
                questionLoc(cur_bank);
            }
        }
        else {
            questionLoc();
        }
    }

    //生产用户刷题记录数据用于测试推荐系统
    public String generatePracticeHistoryForTest(){
        if(!env.equals("dev")){
            return "当前环境不是测试环境，生产测试数据功能已经禁用";
        }
        initMap();
        Date start = new Date();
        for (int i = 1; i <= userNum; i++) {
            String userType;
            User user = new User();
            user.setName("test" + i);
            userService.storeUser(user);
            Integer userId = user.getId();
            double u = new Random().nextDouble();
            if (u < percentMap.get(NORMAL)) userType = NORMAL;
            else if(u >= percentMap.get(NORMAL) && u < percentMap.get(NORMAL) + percentMap.get(TOP)) userType = TOP;
            else userType = EVIL;
            Integer questionNumber = randomInt(lowPracticeNumMap.get(userType), highPracticeNumMap.get(userType));
            System.out.println("userId:" + userId + ", userType:" + userType + ", questionNum:" + questionNumber);
            questionLoc();
            for (int j = 0; j < questionNumber; j++) {
                transformQuestion();
                Question question = questionService.findQuestionByChapterId(cur_chapter, page);
                generateOnePracticeHistory(userId, question.getId(),
                        new Random().nextDouble() < correctMap.get(userType).get(question.getDifficulty()));
            }
        }
        Date end = new Date();
        return "测试数据生成完毕，耗时:" + (end.getTime() - start.getTime());
    }

    private void generateOnePracticeHistory(Integer userId, Integer questionId, Boolean isRight){
        String[] answer = {"A", "B", "C", "D"};
        PracticeHistory practiceHistory = new PracticeHistory();
        practiceHistory.setUserId(userId);
        practiceHistory.setQuestionId(questionId);
        practiceHistory.setIsRight(isRight);
        practiceHistory.setCreateTime(new Date());
        //答案并不重要
        practiceHistory.setAnswer(answer[new Random().nextInt(4)]);
        practiceHistoryDao.save(practiceHistory);
    }

    //[low,high)
    private Integer randomInt(Integer low, Integer high){
        return new Random().nextInt(high - low) + low;
    }

    public String login(Integer userId){
        if(!env.equals(env)){
            return "当前环境不是测试环境，便捷登录方式已禁用";
        }
        User user = userDao.findById(userId).get();
        userService.login(user);
        return user.getUserId();
    }
}
